package com.casstime.ec.cloud.meeting.web.config;

import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.util.Map;

import com.casstime.ec.cloud.meeting.web.util.RedisCache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
	public static final String LONG_TIME_CACHE = "LONG_TIME_CACHE";
	public static final String MIDDLE_TIME_CACHE = "MIDDLE_TIME_CACHE";
	public static final String SHORT_TIME_CACHE = "SHORT_TIME_CACHE";
	public static final String SUPER_SHORT_TIME_CACHE = "SUPER_SHORT_TIME_CACHE";
	public static final String FOUR_HOUR_CACHE = "FOUR_HOUR_CACHE";
	public static final String ONE_DAY_CACHE = "ONE_DAY_CACHE";

	@Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  
        StringRedisTemplate template = new StringRedisTemplate(factory);  
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();  
        om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);  
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);  
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);  
        template.afterPropertiesSet();  
        
        //把 RedisTemplate 注入 RedisCache
        RedisCache.setRedisTemplate(template);
        
        return template;  
    }
	
	@Bean  
    public CacheManager cacheManager(  
            @SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {  
		RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
		
		//默认60秒失效
		redisCacheManager.setDefaultExpiration(60);
		
		//下面可以自定义各个缓存的失效时间
		//下面可以自定义各个缓存的失效时间
			Map<String, Long> expires = Maps.newHashMap();
			expires.put("order.supports.exportCache", (long) 3600);
			expires.put("PRODUCT-SKUCONTROLLER", (long) 600);
			expires.put("FOUR_HOUR_CACHE", (long) (60 * 60 * 4));
			//这个是短期缓存，为了解决一个批量任务里多次调用其他方法耗时的问题，理想情况是任务完成该缓存也销毁
			expires.put(LONG_TIME_CACHE, 3600L);
			expires.put(MIDDLE_TIME_CACHE, 600L);
			expires.put(SHORT_TIME_CACHE, 10L);
			expires.put(SUPER_SHORT_TIME_CACHE, 5L);
			expires.put(ONE_DAY_CACHE, (long) (60 * 60 * 24));
			expires.put("WHITE-BLACK-PERMISSION", 30L);
			
		//expires.put("USER_MENU_CACHE", (long)1000*60*60);
		
		redisCacheManager.setExpires(expires);
		return redisCacheManager;  
    }
	
	@Bean  
    public KeyGenerator wiselyKeyGenerator() {
        return new KeyGenerator() {  
            @Override  
            public Object generate(Object target, Method method, Object... params) {

                StringBuilder sbParams = new StringBuilder(); 
                for (Object obj : params) {  
                	if (obj != null) {
                		sbParams.append(obj.toString());  
                	}
                }
                
                StringBuilder sb = new StringBuilder();  
                sb.append(target.getClass().getName());  
                sb.append(method.getName());
                sb.append(MD5(sbParams.toString()));
                return sb.toString();  
            }  
        };
    }
	
    private String MD5(String inStr) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            return inStr;
        }
        char[] charArray = inStr.toCharArray();
        byte[] byteArray = new byte[charArray.length];
 
        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
 
        byte[] md5Bytes = md5.digest(byteArray);
 
        StringBuffer hexValue = new StringBuffer();
 
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16)
                hexValue.append("0");
            hexValue.append(Integer.toHexString(val));
        }
 
        return hexValue.toString();
    }
}
